/*
 * XMultilineLabel.java
 * 
 * Copyright (c) 2005 - 2007
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.xfc.components;

import java.awt.FontMetrics;

import javax.swing.JLabel;

// TODO: this class should really 1) given it's current width 2) return the size needed to
// lay itself out (the height). This might cause layout flashing, as it would first report
// one min size, then another.

/**
 * 
 * 
 * @author Devon Carew
 */
public class XMultilineLabel
	extends JLabel
{
	private String 	originalText;
	
	private int		preferredWidth = 600;
	
	/**
	 * 
	 */
	public XMultilineLabel()
	{
		
	}

	/**
	 * @param text
	 */
	public XMultilineLabel(String text)
	{
		setText(text);
	}

	public void setText(String text)
	{
		originalText = text;
		
		if (text == null || text.toLowerCase().startsWith("<html"))
		{
			super.setText(text);
		}
		else if (text.indexOf('\n') != -1)
		{
			// TODO: this is potentially a problem - if the text contains newlines but the user
			// wants long lines to wrap as well.
			
			super.setText("<html>" + text.replaceAll("\n", "<br>") + "</html>");
		}
		else
		{
			// It's plain text - no user-specified wrap points. Wrap occording to the given preferred width.
			super.setText("<html>" + wrapLongLines(text).replaceAll("\n", "<br>") + "</html>");
		}
	}
	
	public int getPreferredWidth()
	{
		return preferredWidth;
	}
	
	public void setPreferredWidth(int preferredWidth)
	{
		this.preferredWidth = preferredWidth;
		
		// Re-wrap the text.
		setText(originalText);
	}
	
	private String wrapLongLines(String text)
	{
		// If it's short or empty, just skip the wrapping.
		if (text == null || text.length() < 5 || preferredWidth <= 0)
			return text;
		
		// Tokenize the string into non-ws and ws tokens.
		String[] 	tokens = text.split("\\s");
		String		output = "";
		int			index = 0;
		
		FontMetrics metrics = getFontMetrics(getFont());
		
		// loop through consuming the tokens until the line is longer then the allowed length.
		while (true)
		{
			int 	startIndex = index;
			String 	line = tokens[index];
			
			while (metrics.stringWidth(line) <= preferredWidth)
			{
				index++;
				
				if (index >= tokens.length)
					break;
				
				line += " " + tokens[index];
			}
			
			// We encountered a real long word.
			if (index == startIndex)
				index++;
			
			// Add all the remaining text to the output
			if (output.length() > 0)
				output += "\n";
			
			for (int i = startIndex; i < index; i++)
			{
				if (i != startIndex)
					output += " ";
				output += tokens[i];
			}
			
			if (index >= tokens.length)
				break;
		}
		
		return output;
	}
	
}
